local sugar = SUGAR_webber_the_trainer
local function log(...)
    SUGAR_webber_the_trainer:declare(...)
end

local function GetVisualBB(ent)
    local bbx1,bby1,bbx2,bby2 = ent.AnimState:GetVisualBB()
    return math.abs(bbx1-bbx2),math.abs(bby1-bby2)
end

---血契方法生成器
---@param fn fun(player:ent,data:table|nil):number # data表为监听事件的表,可能为nil
---@return fun(player:ent,data:table|nil)
local function soulAddGenFn(fn)
    return function(player, data)
        if player.components.webbert_soul then
            player.components.webbert_soul:TryDelta(fn(player,data))
        end
    end
end

---@type table<eventID,fun(player:ent,data:table|nil):number>
local event_add_soul = {
    -- 击杀
    killed = function (player, data)
        local val = 0
        ---@cast data event_data_killed
        local victim = data and data.victim
        local maxhp = victim and victim.components.health and victim.components.health.maxhealth
        if maxhp then
            val = maxhp * TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.victim_maxhp_percent * TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.multi_kill
        end
        return val
    end,
    -- 协助击杀
    killed_webber_the_trainer_participate = function (player, data)
        local val = 0
        local victim = data and data.victim
        local maxhp = victim and victim.components.health and victim.components.health.maxhealth
        if maxhp then
            val = maxhp * TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.victim_maxhp_percent * TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.multi_sup
        end
        return val
    end,
    -- work
    working = function (player, data)
        return math.random(8,15)
    end,
    -- 完成work
    ---comment
    ---@param player ent
    ---@param data event_data_finishedwork
    ---@return number
    finishedwork = function (player, data)
        local tar = data and data.target or nil
        if tar and tar:HasTag('oversized_veggie') then
            return math.random(50,200)
        end
        return math.random(20,80)
    end,
    -- 制作物品
    builditem = function (player, data)
        return math.random(6,20)
    end,
    -- 钓鱼
    fishingstrain = function (player, data)
        return math.random(24,50)
    end,
    fishingcatch = function (player, data)
        return math.random(30,60)
    end,
    fishingcollect = function (player, data)
        return math.random(120,240)
    end,
    -- 采摘
    webbert_mod_pick = function (player, data)
        local res = 0
        ---@type ent|nil
        local plant = data and data.plant
        if plant then
            res = res + (plant:HasTag('oversized_veggie') and math.random(700,1200) or 0) + (plant:HasTag('farm_plant') and math.random(70,180) or 0)
        end
        return res
    end,
    -- 烹饪料理
    webbert_mod_cook_preparedfood = function (player, data)
        return math.random(20,80)
    end,
    -- 吃东西
    oneat = function (player, data)
        return math.random(10,20)
    end
}


local function rewards5(inst)
    SUGAR_webber_the_trainer:taskCancel(inst,'task_intime_cancel_webbertsoul_buytime5_heal')
    -- 取消上一次的倒计时并开始计时
    SUGAR_webber_the_trainer:taskDoInTime(inst,'task_intime_cancel_webbertsoul_buytime5_inbattle',10,function()
        SUGAR_webber_the_trainer:taskDoPeriodicForAWhile(inst,'task_intime_cancel_webbertsoul_buytime5_heal',TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy.buy_5_heal_interval,nil,function ()
            if inst and inst.components.health and not inst:HasTag('playerghost') and inst.components.webbert_soul then
                local buy5 = inst.components.webbert_soul['buy_times_5'] or 0
                inst.components.health:DoDelta(TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy.buy_5_heal_amount*buy5,true)
            end
        end,nil,0)
    end,true)
end

AddPrefabPostInit('webbert',
function (inst)
    if not TheWorld.ismastersim then
        return inst
    end
    inst:AddComponent('webbert_soul')
    for k,v in pairs(event_add_soul) do
        inst:ListenForEvent(k,soulAddGenFn(v))
    end

    -- 血契 自然恢复 购买相关
    rewards5(inst)
    inst:ListenForEvent('healthdelta',
    ---comment
    ---@param this ent
    ---@param data event_data_healthdelta
    function (this, data)
        local amount = data and data.amount
        if amount < 0 then
            rewards5(inst)
        end
    end)

    local combo_need = 5
    local atkspeed_buff_duration = 3
    local cd = 5
    local _c = 0 -- 连续攻击5次,会提升攻速3秒,内置cd5秒

    local combo_need2 = 5
    local dmgtaken_buff_duration = 5
    local cd2 = 10
    local _c2 = 0 -- 连续攻击5次后,会给敌方5秒的易伤,内置cd10秒
    inst:ListenForEvent('onhitother',
    ---comment
    ---@param this ent
    ---@param data event_data_onhitother
    function (this, data)
        local victim = data and data.target or nil
        -- 不在buff或cd中 才继续
        local buytimes6 = inst.components.webbert_soul['buy_times_6'] or 0
        if buytimes6 > 0 and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_atkspeed_cancelbuff') and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_atkspeed_cd') then
            -- 叠层数
            _c = _c + 1
            -- 持续攻击不掉层,1秒内不攻击 层数清零
            sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_atkspeed_counter',1,function ()
                _c = 0
            end,true)
            -- 层数叠好
            if _c >= combo_need then
                -- 触发攻速buff
                if inst.Modifier_common_atkspeedmodifier then
                    inst:Modifier_common_atkspeedmodifier(inst,buytimes6*TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy.buy_6_atkspd,'webbert_soul_buytimes6')
                end
                if inst.components.locomotor then
                    inst.components.locomotor:SetExternalSpeedMultiplier(inst,'taskintime_webbertsoul_buytime_6_speedmult',1.2)
                end
                local fx = SpawnPrefab('fx_webbert_misc')
                local scale = 2
                fx.Transform:SetScale(scale,scale,scale)
                fx.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
                fx.AnimState:SetLightOverride(1)
                ---@cast fx ent_fx
                fx.entity:AddFollower()
                fx.Follower:FollowSymbol(inst.GUID, nil, 0,-200,0)
                fx:fn_fx_webbert_misc('fx_webbert_flame_flow','fx_webbert_flame_flow','idle',false,true)
                -- 攻击速度buff持续中
                sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_atkspeed_cancelbuff',atkspeed_buff_duration,function ()
                    if inst.RemoveModifier_common_atkspeedmodifier then
                        inst:RemoveModifier_common_atkspeedmodifier(inst,'webbert_soul_buytimes6')
                    end
                    if inst.components.locomotor then
                        inst.components.locomotor:RemoveExternalSpeedMultiplier(inst,'taskintime_webbertsoul_buytime_6_speedmult')
                    end
                    -- 时间到进入内置cd
                    sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_atkspeed_cd',cd)
                end,true)
            end
        end
        local buytimes8 = inst.components.webbert_soul['buy_times_8'] or 0
        if buytimes8 > 0 and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_8_cancelbuff') and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_8_cd') then
            _c2 = _c2 + 1
            sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_8_counter',1,function ()
                _c2 = 0
            end,true)
            if _c2 >= combo_need2 then
                if victim and victim.components.combat then
                    victim.components.combat.externaldamagetakenmultipliers:SetModifier(inst,1+buytimes8*TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy.buy_8_dmgtaken,'webbert_soul_buytimes8')
                    local fx = SpawnPrefab('particle_webbert_globalsquare')
                    local w,h = GetVisualBB(victim)
                    if fx.particle_send_data_to_client then
                        fx:particle_send_data_to_client(w)
                    end
                    fx.entity:AddFollower()
                    fx.Follower:FollowSymbol(victim.GUID, nil, 0,-200,0)
                    sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_8_cancelbuff',dmgtaken_buff_duration,function()
                        if victim and victim.components.combat then
                            victim.components.combat.externaldamagetakenmultipliers:RemoveModifier(inst,'webbert_soul_buytimes8')
                        end
                        if fx and fx:IsValid() then
                            fx:Remove()
                        end
                        fx = nil
                        sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_8_cd',cd2)
                    end,true)
                end
            end
        end
        -- 眩晕
        local stun_buff_duration = 3
        local cd3 = 5
        local buytimes10 = inst.components.webbert_soul['buy_times_10'] or 0
        if buytimes10 > 0 and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_10_cancelbuff') and not sugar:taskIfExist(inst,'taskintime_webbertsoul_buytime_10_cd') and victim and sugar:checkAlive(victim) and victim.components.locomotor and victim.brain and math.random() <= TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy.buy_10_stunchance*buytimes10 then -- 只有有脑子和移动组件的才能被stun
            victim.components.locomotor:Stop()
            victim:StopBrain()
            local w,h = GetVisualBB(victim)
            local fx = SpawnPrefab('particle_webbert_stun_star')
            if fx.particle_send_data_to_client then
                fx:particle_send_data_to_client(w,h)
            end
            fx.entity:AddFollower()
            fx.Follower:FollowSymbol(victim.GUID, nil, 0, 0, 0)
            sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_10_cancelbuff',stun_buff_duration,function ()
                if victim and victim:IsValid() then
                    victim:RestartBrain()
                end
                if fx and fx:IsValid() then
                    fx:Remove()
                end
                fx = nil
                sugar:taskDoInTime(inst,'taskintime_webbertsoul_buytime_10_cd',cd3)
            end,true)
        end
    end)

    if inst.components.foodaffinity == nil then
        inst:AddComponent('foodaffinity')
    end
    -- 吃生肉拉肚子
    inst:ListenForEvent('oneat',
    ---comment
    ---@param this ent
    ---@param data event_data_oneat
    function (this, data)
        local food = data and data.food or nil
        if food and food:HasTag('meat') and food:HasTag('rawmeat') then
            local buy7 = inst.components.webbert_soul and inst.components.webbert_soul['buy_times_7'] or 0
            if math.random() < buy7/10 then
                inst:AddDebuff('buff_webbert_soul_buy_times_7_debuff','buff_webbert_soul_buy_times_7_debuff')
            end
        end
    end)

    -- 崩解余震','被击杀的目标引起一个基础伤害为30点的范围物理伤害.无cd.每次购买增加1点范围伤害
    inst:ListenForEvent('killed',
    ---comment
    ---@param this ent
    ---@param data event_data_killed
    function (this, data)
        local victim = data and data.victim or nil
        if victim then
            local buy9 = inst.components.webbert_soul and inst.components.webbert_soul['buy_times_9'] or 0
            if buy9 > 0 then
                local _db = TUNING.MOD_WEBBER_THE_TRAINER.webbert_soul.buy
                local pt = victim:GetPosition()
                local fx = SpawnPrefab('fx_webbert_misc')
                ---@cast fx ent_fx
                fx:fn_fx_webbert_misc('fx_webbert_burn_spread_ring','fx_webbert_burn_spread_ring','idle',false,true,2,true,pt)
                local ents = TheSim:FindEntities(pt.x, 0, pt.z, 3, {'_combat','_health'}, sugar.tags_notenemy)
                for _,v in ipairs(ents) do
                    if v ~= victim and v.components.combat and sugar:checkAlive(v) then
                        inst:DoTaskInTime(0,function ()
                            if v and v:IsValid() then
                                v.components.combat:GetAttacked(inst,_db.buy_9_aoedmg + buy9*_db.buy_9_peradd)
                            end
                        end)
                    end
                end
            end
        end
    end)
end)